package com.slipper.system.role;

import com.slipper.common.bo.Result;
import com.slipper.common.permit.PermitAll;
import com.slipper.common.tree.Node;
import com.slipper.common.tree.TreeInfo;
import com.slipper.common.tree.TreeUtil;
import com.slipper.common.util.ResultUtil;
import com.slipper.system.api.employee.bo.EmployeeBO;
import com.slipper.system.api.menu.bo.MenuBO;
import com.slipper.system.api.menu.bo.MenuPrivilegeBO;
import com.slipper.system.api.menu.service.IMenuPrivilegeSv;
import com.slipper.system.api.menu.service.IMenuSv;
import com.slipper.system.api.role.bo.RoleBO;
import com.slipper.system.api.role.service.IRoleSv;
import com.slipper.system.common.Constants;
import com.slipper.system.common.UserDetail;
import javax.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 角色信息表
 * 
 * @date 2019-10-03 14:09:46
 */
@RestController
@RequestMapping("/role")
public class RoleController {
    @Resource
    private IRoleSv roleSv;
    @Resource
    private IMenuSv menuSv;
    @Resource
    private IMenuPrivilegeSv menuPrivilegeSv;

    @PermitAll
    @PostMapping("/queryList")
    public String queryList(@RequestBody RoleBO bo) {
        if (!Constants.getCurrentUser().isSuperAdmin()) {
            bo.setOnlyCreateId(Constants.getCurrentUser().getEmployeeId());
        }
        return ResultUtil.toJson(roleSv.queryList(bo));
    }
    
    @PostMapping("/queryPage")
    public String queryPage(@RequestBody RoleBO bo) {
        if (!Constants.getCurrentUser().isSuperAdmin()) {
            bo.setOnlyCreateId(Constants.getCurrentUser().getEmployeeId());
        }
        return ResultUtil.toJson(roleSv.queryPage(bo));
    }

    @PostMapping("/save")
    public String save(@RequestBody RoleBO bo) {
        UserDetail userDetail = Constants.getCurrentUser();
        if (!userDetail.isSuperAdmin() && bo.getPower() == 0) {
            return ResultUtil.toErrorJson("非超级管理员，只允许添加/修改普通角色！");
        }

        if (bo.getPower() == null) {
            bo.setPower(5);
        }
        if (!userDetail.isSuperAdmin() && bo.getPower() <= 4) {
            return ResultUtil.toErrorJson("非超级管理员，权力大小值必须大于4！");
        }

        EmployeeBO employee = Constants.getCurrentUser().getEmployee();
        if (!Constants.getCurrentUser().isSuperAdmin() && bo.getId() != null ) {
            Result<RoleBO> role = this.roleSv.queryBy(bo);
            if (role.getData().getCreateId() != null
                    && !role.getData().getCreateId().equals(employee.getId())) {
                return ResultUtil.toErrorJson("此角色不由您创建，不允许修改！");
            }
        }

        bo.setUpdateId(employee.getId());
        bo.setCreateId(employee.getId());
        return ResultUtil.toJson(roleSv.save(bo));
    }

    @PostMapping("/queryBy")
    public String queryBy(@RequestBody RoleBO bo) {
        return ResultUtil.toJson(roleSv.queryBy(bo));
    }

    @PostMapping("/delete")
    public String delete(@RequestBody RoleBO bo) {
        return ResultUtil.toJson(roleSv.delete(bo));
    }
    
    @PostMapping("/queryPower")
    public String queryPower(@RequestBody RoleBO bo) {
        Map<String, Object> model = new HashMap<>();
        model.put("privilegeIds", this.roleSv.queryPower(bo).getData());
        
        String employeeId = null;
        if (!Constants.getCurrentUser().isSuperAdmin()) {
            employeeId = Constants.getCurrentUser().getEmployeeId();
        }
        MenuBO qo = new MenuBO();
        // qo.setType("1");
        qo.setEmployeeId(employeeId);
        Result<List<MenuBO>> menuList = this.menuSv.queryList(qo);
        // 补充父菜单
        Set<String> idList = new HashSet<>();
        Set<String> allPidList = new HashSet<>();
        for (MenuBO menu : menuList.getData()) {
            if (!"0".equals(menu.getParentId())) {
                allPidList.add(menu.getParentId());
            }
            idList.add(menu.getId());
        }
        for (String id : idList) {
            allPidList.remove(id);
        }
        for (String id : allPidList.toArray(new String[] {})) {
            this.addParent(id, allPidList, menuList.getData());
        }

        MenuPrivilegeBO menuPrivilegeBO = new MenuPrivilegeBO();
        menuPrivilegeBO.setEmployeeId(employeeId);
        List<MenuPrivilegeBO> privilegeList = this.menuPrivilegeSv.queryList(menuPrivilegeBO).getData();

        TreeInfo treeInfo = new TreeInfo("菜单树");
        treeInfo.setRootId(Constants.ROOT_ID);
        treeInfo.setIdField("id");
        treeInfo.setPidField("parentId");
        treeInfo.setTextField("name");
        treeInfo.setHrefField("url");
        treeInfo.setSortField("ordinal");
        Node root = TreeUtil.buildTree(treeInfo, menuList.getData());
        this.fillPrivilege(root, 0, privilegeList);
        model.put("menus", this.expandData(root));
        
        return ResultUtil.toJson(model);
    }
    
    private void addParent(String menuId, Set<String> allPidList, List<MenuBO> menuList) {
        Result<MenuBO> menuBO = this.menuSv.queryBy(menuId);
        if (menuBO != null) {
            menuList.add(menuBO.getData());
            if (menuBO.getData().getParentId() != null &&
                    !"0".equals(menuBO.getData().getParentId())
                    && allPidList.add(menuBO.getData().getParentId())) {
                this.addParent(menuBO.getData().getParentId(), allPidList, menuList);
            }
        }
    }
    
    private void fillPrivilege(Node node, int level, List<MenuPrivilegeBO> privilegeList) {
        if (node.getChildren().isEmpty()) {
            if (level <= 2) {
                Node n = new Node(node.getId());
                n.setId(node.getId());
                n.setText("");
                node.addChildren(n);
                this.fillPrivilege(node, level, privilegeList);
            } else if (node.getId() != null) {
                List<MenuPrivilegeBO> list = this.getPrivilegeList((String) node.getId(), privilegeList);
                for (MenuPrivilegeBO operator : list) {
                    Node n = new Node(node.getId());
                    n.setId(operator.getId());
                    n.setText(operator.getName());
                    n.setOrderBy(operator.getOrdinal());
                    n.setData(operator);
                    node.addChildren(n);
                }
            }
        } else {
            level = level + 1;
            for (Node n : node.getChildren()) {
                fillPrivilege(n, level, privilegeList);
            }
        }
    }
    
    private List<MenuPrivilegeBO> getPrivilegeList(String menuId, List<MenuPrivilegeBO> privilegeList) {
        List<MenuPrivilegeBO> resultList = new LinkedList<>();
        for (MenuPrivilegeBO privilege : privilegeList) {
            if (menuId.equals(privilege.getMenuId())) {
                resultList.add(privilege);
            }
        }
        return resultList;
    }
    
    private List<Map<String, Object>> expandData(Node node) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (Node first : node.getChildren()) { // 第一层
            for (Node second : first.getChildren()) { // 第二层
                for (Node third : second.getChildren()) { // 第三层
                    Map<String, Object> data = new HashMap<>();
                    data.put("first", first.getText());
                    data.put("second", second.getText());
                    data.put("third", third.getText());
                    data.put("thirdId", third.getId());
                    data.put("children", third.getChildren());
                    
                    result.add(data);
                }
            }
        }
        return result;
    }
    
    @PostMapping("/savePower")
    public String savePower(@RequestBody RoleBO bo) {
        return ResultUtil.toJson(this.roleSv.savePower(bo));
    }
}
